﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace Client
{
    class PacketController
    {
        private const int NCCport = 9785;
        private Socket _client;
        readonly ASCIIEncoding _encoder = new ASCIIEncoding();
        readonly byte[] _buffer = new byte[4096];
        public static bool Connected = false;

        private readonly CPCC _cpcc;

        public delegate void LogEventHandler(string command);
        public static event LogEventHandler Log;

        public PacketController(CPCC cpcc)
        {
            _cpcc = cpcc;
            Connect("127.0.0.1", NCCport);
        }

        public void Connect(String strIpAddress, int portNo)
        {
            _client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // get the remote IP address...
            var ipAddress = IPAddress.Parse(strIpAddress);
            //create the end point
            var ipEndPoint = new IPEndPoint(ipAddress, portNo);
            //connect to the remote host...
            _client.Connect(ipEndPoint);
            //watch for data ( asynchronously )...
            WaitForData();
        }

        private void WaitForData()
        {
            // now start to listen for any data...
            _client.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, OnDataReceived, null);
        }

        private void OnDataReceived(IAsyncResult asyn)
        {
            //end receive...
            var bytesReceivedCount = _client.EndReceive(asyn);
            var memoryStream = new MemoryStream(_buffer, 0, bytesReceivedCount);

            String received = _encoder.GetString(_buffer);
            Console.WriteLine("PC : " + received);
            QueryHandler(received);

            WaitForData();
        }

        //tnie otrzymaną wiadomość, i w zależności od jej zawartości przekazuje do takiego elementu: CPCC, NCC, CC, RC, LRM
        private void QueryHandler(string received)
        {
            string[] query = received.Split(' ');

            switch (query[0])
            {
                case "call_teardown":
                    //Log("[PC --> CPCC]");
                    _cpcc.CallTeardown(query[1], query[2]);
                    break;
                case "call_request":
                    //Log("[PC --> CPCC]");
                    _cpcc.CallRequest(query[1], query[2]);
                    break;
                default:
                    Log("Nieprawidłowa wiadomość pomiędzy elementami warstwy sterowania! Treść wiadomości: " + received);
                    break;

            }
        }

        public void Send(string message)
        {
            _client.BeginSend(_encoder.GetBytes(message), 0, _encoder.GetBytes(message).Length, SocketFlags.None, null, null);
        }

        public void SendACK(string message)
        {
            try
            {
                //Log("[--> PC]");
                _client.Send(_encoder.GetBytes(message));
            }
            catch (Exception)
            {
                Console.WriteLine("Blad");
            }
        }
    }
}
